// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: qiang

#pragma once

#include <rapidjson/document.h>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/mercado/api_util/rate_tracker.h"
#include "coin2/exchange/mercado/order_v4/error_code.h"
#include "coin2/exchange/mercado/symbology/product.h"

namespace coin2::exchange::mercado::order_v4 {

class MercadoParser : public base::order::BaseParser {
 public:
  using JsonValue = rapidjson::GenericValue<rapidjson::UTF8<>>;
  using ProductOrderBundle = coin::proto::ProductOrderBundle;
  using ProductOrderElement = coin::proto::ProductOrderElement;

 public:
  const ParseResult& ParseRawMessage(const RawMessage& msg) override;
  AccountBalance ParseBalance(const JsonValue& doc) override;
  bool ParseRawBalance(const JsonValue& doc, RawBalanceMap* raw_balance_map);

 private:
  void ParseAccounts();
  void ParseToken();
  void ParseListOrder();
  void ParseOrderInfo(const rapidjson::GenericValue<rapidjson::UTF8<>>& document);
  void ParseFilledExecutions(const JsonValue& doc);
  void ParseSubmitResponse();
  void ParseCancelResponse();
  void ParseWsMessage();

  void ParseRestSpotAccountBalance();

 private:
  bool IsMercadoSpotErrMessage(const JsonValue& doc);
  int64_t GetTimestamp(const std::string& time_str);
  int64_t GetProcOrderId(const JsonValue& data);
  coin::proto::OrderSide GetOrderSide(const std::string& side);
  coin::proto::OrderType GetOrderType(const std::string& type);
  void SetOrderStatus(ProductOrderElement* order, const std::string& status);
  std::string GetExchangeOrderId(
      const std::string_view& symbol,
      const std::string_view& exchange_order_id);

 private:
  bool is_account_balance_initialized_ = false;
};

}  // namespace coin2::exchange::mercado::order_v4
